#include "flash_if.h"


/* 定义 Flash 扇区表，包含每个扇区的编号和起始地址 */
const FlashSectorInfo f4xx_flash_tbl[] = {
    { FLASH_SECTOR_0, 0x08000000 },  // 扇区 0, 16KB
    { FLASH_SECTOR_1, 0x08004000 },  // 扇区 1, 16KB
    { FLASH_SECTOR_2, 0x08008000 },  // 扇区 2, 16KB
    { FLASH_SECTOR_3, 0x0800C000 },  // 扇区 3, 16KB
    { FLASH_SECTOR_4, 0x08010000 },  // 扇区 4, 64KB
    { FLASH_SECTOR_5, 0x08020000 },  // 扇区 5, 128KB
    { FLASH_SECTOR_6, 0x08040000 },  // 扇区 6, 128KB
    { FLASH_SECTOR_7, 0x08060000 },  // 扇区 7, 128KB
    { FLASH_SECTOR_8, 0x08080000 },  // 扇区 8, 128KB
    { FLASH_SECTOR_9, 0x080A0000 },  // 扇区 9, 128KB
    { FLASH_SECTOR_10, 0x080C0000 }, // 扇区 10, 128KB
    { FLASH_SECTOR_11, 0x080E0000 }  // 扇区 11, 128KB
};

const FlashUpdateInfo flash_update_tbl[] = 
{
	{FlashFunc_BOOT, 0, 2},				//48kb
	{FlashFunc_PARAM, 3, 3},			//16kb
	{FlashFunc_APP, 4, 7},				//448kb
	{FlashFunc_APP, 8, 11},				//512kb
};



/**
  * @brief  擦除指定扇区。
  * @param  StartSector: 起始扇区编号（例如 FLASH_SECTOR_6）。
  * @param  NbSectors: 要擦除的扇区数目。
  * @retval HAL 状态，HAL_OK 表示成功。
  */
HAL_StatusTypeDef FLASH_EraseSectors(uint32_t StartSector, uint32_t NbSectors)
{
    HAL_StatusTypeDef status;
    FLASH_EraseInitTypeDef EraseInitStruct;
    uint32_t SectorError = 0;

    // 解锁 Flash
    HAL_FLASH_Unlock();

    // 配置擦除参数
    EraseInitStruct.TypeErase     = FLASH_TYPEERASE_SECTORS;
    EraseInitStruct.VoltageRange  = FLASH_VOLTAGE_RANGE_3; // 适用于 2.7V ~ 3.6V
    EraseInitStruct.Sector        = StartSector;
    EraseInitStruct.NbSectors     = NbSectors;

    // 执行擦除操作
    status = HAL_FLASHEx_Erase(&EraseInitStruct, &SectorError);

    // 锁定 Flash
    HAL_FLASH_Lock();

    return status;
}

/**
  * @brief  写入一个 32 位数据（word）到指定地址。
  * @param  Address: 目标地址，必须是 4 字节对齐。
  * @param  Data: 要写入的 32 位数据。
  * @retval HAL 状态，HAL_OK 表示成功。
  */
HAL_StatusTypeDef FLASH_WriteWord(uint32_t Address, uint32_t Data)
{
    HAL_StatusTypeDef status;

    // 解锁 Flash
    HAL_FLASH_Unlock();

    // 写入 32 位数据，编程类型选择 WORD 编程
    status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, Address, Data);

    // 锁定 Flash
    HAL_FLASH_Lock();

    return status;
}

/**
  * @brief  从指定地址读取一个 32 位数据。
  * @param  Address: 要读取的地址。
  * @retval 读取到的 32 位数据。
  */
uint32_t FLASH_ReadWord(uint32_t Address)
{
    // 直接将 Flash 映射内存地址转换为指针读取数据
    return *((volatile uint32_t *)Address);
}


HAL_StatusTypeDef FLASH_WriteBuffer(uint32_t Address, uint32_t *Data, uint32_t Length)
{
    HAL_StatusTypeDef status = HAL_OK;
    uint32_t currentAddress = Address;
    uint32_t i;

    // 检查起始地址是否 4 字节对齐
    if(currentAddress % 4 != 0)
    {
        return HAL_ERROR;
    }

    // 解锁 Flash，一次性解锁进行多个写入操作
    HAL_FLASH_Unlock();

    for(i = 0; i < Length; i++)
    {
        status = HAL_FLASH_Program(FLASH_TYPEPROGRAM_WORD, currentAddress, Data[i]);
        if(status != HAL_OK)
        {
            // 写入失败，退出循环
            break;
        }
        currentAddress += 4;  // 下一个 32 位数据地址偏移 4 字节
    }

    // 锁定 Flash
    HAL_FLASH_Lock();
		
		    // 自动比对验证写入数据是否正确
    for(i = 0; i < Length; i++)
    {
        if(FLASH_ReadWord(Address + i*4) != Data[i])
        {
            // 如果验证失败，则返回错误码
            return HAL_ERROR;
        }
    }

    return status;
}
